class NoInlineClass {
private fun runLambda(block: () -> Unit) {
println("runLambda start")
block()
println("runLambda end")
}
fun run() {
println("start")
runLambda {
println("runLambda")
}
println("end")
}
}
會被編譯成
public final class NoInlineClass {
private final void runLambda(Function0 block) {
String var2 = "runLambda start";
boolean var3 = false;
System.out.println(var2);
block.invoke();
var2 = "runLambda end";
var3 = false;
System.out.println(var2);
}
public final void run() {
String var1 = "start";
boolean var2 = false;
System.out.println(var1);
this.runLambda((Function0)null.INSTANCE);
var1 = "end";
var2 = false;
System.out.println(var1);
}
}
Java透過Function0回調來實現Lambda
所以每次run()被呼叫時,都會產生 Function0 INSTANCE
頻繁呼叫就會產生大量INSTANCE,若是capturing lambda會變得更糟糕
inline
class InlineClass {
private inline fun runLambda(block: () -> Unit) {
println("runLambda start")
block()
println("runLambda end")
}
fun run() {
println("start")
runLambda {
println("runLambda")
}
println("end")
}
}
public final class InlineClass {
private final void runLambda(Function0 block) {
int $i$f$runLambda = 0;
String var3 = "runLambda start";
boolean var4 = false;
System.out.println(var3);
block.invoke();
var3 = "runLambda end";
var4 = false;
System.out.println(var3);
}
public final void run() {
String var1 = "start";
boolean $i$f$runLambda = false;
System.out.println(var1);
$i$f$runLambda = false;
String var3 = "runLambda start";
boolean var4 = false;
System.out.println(var3);
int var5 = false;
String var6 = "runLambda";
boolean var7 = false;
System.out.println(var6);
var3 = "runLambda end";
var4 = false;
System.out.println(var3);
var1 = "end";
$i$f$runLambda = false;
System.out.println(var1);
}
}
簡單說,inline fun裡的程式碼會被整段複製
不再產生Function0 INSTANCE
Local & Non-local return
class API {
private fun doSomeThing(block: () -> Unit) {
println("start api")
block()
println("finish api")
}
fun callAPI() {
doSomeThing {
println("test api")
return //錯誤, IDE提示 'return' is not allowed here
return@doSomeThing //正確, 但 println("finish api")會被執行
}
}
}
加入inline前,只允許使用 return@doSomeThing ,這是local return,只能跳離Lambda block
加入inline後,可以使用 return ,這是non-local return,可以跳離整個fun
noinline
不複製該段lambda
private inline fun doSomeThing(block1: () -> Unit, noinline block2: () -> Unit)
crossinline
不允許該段lambda使用non-local return
class API {
private inline fun doSomeThing(crossinline block1: () -> Unit) {
println("start api")
block1()
println("finish api")
}
fun callAPI() {
doSomeThing {
return //Not allowed
return@doSomeThing //Only allowed this
}
}
}
ref: https://stackoverflow.com/questions/44471284/when-to-use-an-inline-function-in-kotlin